// 由于过多的在HTML文件中引入scrit标签，会影响加载速度，所以将多个js文件 合并到一个js文件中 ，
// 注意 ： 合并的时候，每个自调用函数的结尾处要以分号结束  或者 在每个自调用函数的开头添加分号；；


// -------Tools.js-----------
;(function(){
  var Tools = {
  getRandom : function(min , max){
    return Math.floor(Math.random()* (max - min + 1)) + min;
  }
}
window.Tools = Tools;
})()



// ---------------- Food.js-------------
// 所有的js文件中书写代码，都是全局作用域

// 函数名 fn 可能会导致命名冲突，所在这样开启一个新的作用域不合适
// function fn(){
//   // 局部作用域
//   var n = 1;
// }
// fn();

// 自调用函数 --- 开启一个新的作用域， 避免命名冲突
;(function (window) {
  var position = "absolute";
  var element = [];
  // 创建食物的构造函数
  function Food(options) {
    options = options || {};
    this.width = options.width || 20;
    this.height = options.height || 20;
    this.x = options.x || 0;
    this.y = options.y || 0;
    this.color = options.color || 'blue';
  }
  Food.prototype.render = function (map) {
    remove();
    this.x = Tools.getRandom(0, map.offsetWidth / this.width - 1) * this.width;
    this.y = Tools.getRandom(0, map.offsetHeight / this.height - 1) * this.height;
    // 动态创建div 页面上显示的食物
    var div = document.createElement('div');
    map.appendChild(div);
    element.push(div)
    // 设置div的样式
    div.style.left = this.x + 'px';
    div.style.top = this.y + 'px';
    div.style.width = this.width + 'px';
    div.style.height = this.height + 'px';
    div.style.position = position;
    div.style.backgroundColor = this.color;
  }

  function remove() {
    for (var i = element.length- 1; i >= 0; i--) {
      // 删除div
      element[i].parentNode.removeChild(element[i]);
      // 删除数组中的元素
      // 删除数组元素
      // 第一个参数，从哪个元素开始删除
      // 第二个参数，删除几个元素
      element.splice(i, 1);

    }
  }
  window.Food = Food;
})(window)


// ---------------snack.js----------------
// 自调用函数，开启一个新的局部作用域。防止命名冲突
;(function () {
  var position = "absolute";
  var element = [];
  function Snack(options) {
    options = options || {};
    // 蛇节的大小
    this.width = options.width || 20;
    this.height = options.height || 20;
    // 蛇移动的方向
    this.direction = options.direction || 'right';
    // 蛇的身体（蛇节） 第一个元素是蛇头
    this.body = [
      { x: 3, y: 2, color: 'red' },
      { x: 2, y: 2, color: 'blue' },
      { x: 1, y: 2, color: 'blue' }
    ];


  }

  // 将蛇渲染到页面上
  Snack.prototype.render = function (map) {
    remove();
    for (var i = 0, len = this.body.length; i < len; i++) {
      
      // 蛇节
      var object = this.body[i];
      var div = document.createElement('div');
      element.push(div);
      map.appendChild(div);
      div.style.width = this.width + 'px';
      div.style.height = this.height + 'px';
      div.style.position = position;
      div.style.left = object.x * this.width + 'px';
      div.style.top = object.y * this.height + 'px';
      div.style.backgroundColor = object.color;
    }

  }

  // 让蛇运动起来
  Snack.prototype.move = function (food,map) {
    // 控制蛇的身体移动（当前蛇节到上一个蛇节的位置）
    for (var i = this.body.length - 1; i > 0; i--) {
      this.body[i].x = this.body[i - 1].x;
      this.body[i].y = this.body[i - 1].y;
    }
    // 控制蛇头的移动
    // 控制蛇移动的方向
    var head = this.body[0];
    switch (this.direction) {
      case "right":
        head.x += 1;
        break;
      case "left":
        head.x -= 1;
        break;
      case 'top':
        head.y -= 1;
        break;
      case "bottom":
        head.y += 1;
        break;  
    }

    // 2.4 判断蛇头是否和食物的坐标重合
    var headX = head.x * this.width;
    var headY = head.y * this.height;
    if(headX === food.x && headY === food.y){
      var last = this.body[this.body.length - 1];
      this.body.push({
        x : last.x,
        y : last.y,
        color : last.color
      })
    // 随机在地图上重新生成食物
      food.render(map);
    }
    // 让蛇增加一节
  }

  // 删除蛇节
  function remove (){
    for(var i = element.length - 1; i >=0; i--){
      element[i].parentNode.removeChild(element[i]);
      element.splice(i,1);
    }
  }

  // 暴露构造函数给外部
  window.Snack = Snack;
})()


// --------game.js--------------
// 自调用函数，开启一个新的局部作用域，避免命名冲突
;(function(){
  var that;
  function Game(map){
    this.food = new Food();
    this.snack = new Snack();
    this.map = map;
    that = this;
  }
  Game.prototype.start = function(){
    this.food.render(this.map);
    this.snack.render(this.map);
    // 1 把蛇和食物对象，渲染到地图上
    
    // 2 开始游戏的逻辑
    // 2.1 让蛇移动起来  
    runSnack();
    
    // 2.2 通过键盘控制蛇移动的方向
    bindKey();
    // 2.3 当蛇遇到食物 做相应的处理
  }

  // 定义一个私有函数
  function runSnack (){
    var timeId = setInterval(function(){
      this.snack.move(this.food,this.map);
      this.snack.render(this.map);
      // 2.2 当蛇遇到边界的时候游戏结束
      var maxX = this.map.offsetWidth / this.snack.width;
      var maxY = this.map.offsetHeight / this.snack.height;
      var headX = this.snack.body[0].x;
      var headY = this.snack.body[0].y;
      if(headX < 0 || headX >= maxX){
        alert("Game Over");
        clearInterval(timeId);
        return;
      }
      if(headY < 0 || headY > maxY){
        alert("Game Over");
        clearInterval(timeId);
        return;
      }
    }.bind(that),150)
  }

  // 通过键盘控制蛇移动的方向
  function bindKey (){
    document.addEventListener('keydown',function(e){
      // 37 --- left
      // 38----top
      // 39 --- right
      // 40--- bottom
      switch(e.keyCode){
        case 37:
        this.snack.direction = "left";
        break;
        case 38:
        this.snack.direction = "top";
        break;
        case 39:
        this.snack.direction = "right";
        break;
        case 40:
        this.snack.direction = "bottom";
        break;
      }
    }.bind(that),false)
  }

  // 暴露构造函数到外部
  window.Game = Game;
})()


// ------------------main.js  调用-----------
;(function () {
  var map = document.getElementById('map');
  var game = new Game(map)
  game.start();
})()
